package com.ruyuan.little.project.rocketmq.api.login.service.impl;

import com.alibaba.fastjson.JSON;
import com.ruyuan.little.project.common.dto.CommonResponse;
import com.ruyuan.little.project.common.enums.ErrorCodeEnum;
import com.ruyuan.little.project.common.enums.LittleProjectTypeEnum;
import com.ruyuan.little.project.mysql.api.MysqlApi;
import com.ruyuan.little.project.mysql.dto.MysqlRequestDTO;
import com.ruyuan.little.project.rocketmq.api.login.enums.FirstLoginStatusEnum;
import com.ruyuan.little.project.rocketmq.api.login.dto.LoginRequestDTO;
import com.ruyuan.little.project.rocketmq.api.login.service.LoginService;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;


@Service
public class LoginServiceImpl implements LoginService {

    private static final Logger LOGGER = LoggerFactory.getLogger(LoginServiceImpl.class);

    @Resource(name = "loginProducer")
    private DefaultMQProducer loginProducer;

    @Value("${rocketmq.login.topic}")
    private String loginTopic;

    /**
     * mysql dubbo api接口
     */
    @Reference(version = "1.0.0",
            interfaceClass = MysqlApi.class,
            cluster = "failfast",check=false)
    private MysqlApi mysqlApi;

    /**
     * 用户第一次登录需要发放优惠券
     * 1. 判断时候是第一次登录
     *  1.1 第一次登录，发送登录消息到特定TOPIC，并且跟你第一次登录标记位
     *  1.2 非第一登录，直接返回
     * @param loginRequestDTO 登陆信息
     */
    @Override
    public void firstLoginDistributeCoupon(LoginRequestDTO loginRequestDTO) {

        if (!isFirstLogin(loginRequestDTO)){
            LOGGER.info("userId:{} not first login", loginRequestDTO.getUserId());
            return;
        }

        this.updateFirstLoginStatus(loginRequestDTO.getPhoneNumber(), FirstLoginStatusEnum.NO);

        this.sendFirstMessage(loginRequestDTO);
    }

    /**
     * 发送登录消息
     * @param loginRequestDTO
     */
    private void sendFirstMessage(LoginRequestDTO loginRequestDTO) {
        Message loginMessage = new Message();
        loginMessage.setTopic(loginTopic);
        loginMessage.setBody(JSON.toJSONString(loginRequestDTO).getBytes(StandardCharsets.UTF_8));

        try {
            LOGGER.info("start send login success notify message");
            SendResult sendResult = loginProducer.send(loginMessage);
            LOGGER.info("end send login success notify message,sendResult:{}",JSON.toJSONString(sendResult));
        } catch (Exception e) {
            LOGGER.error("send login success notify message fail,error message:{}",e);
        }
    }

    /**
     * 更新第一次登录标记位
     *
     * 正常情况是会调用DAO的，才用mybatis进行数据库的访问
     * @param phoneNumber
     * @param firstLoginStatusEnum
     */
    private void updateFirstLoginStatus(String phoneNumber, FirstLoginStatusEnum firstLoginStatusEnum) {
        MysqlRequestDTO mysqlRequestDTO = new MysqlRequestDTO();
        mysqlRequestDTO.setSql("update t_member set first_login_status = ? WHERE beid = 1563 and mobile = ?");
        ArrayList<Object> params = new ArrayList<>();
        params.add(firstLoginStatusEnum.getStatus());
        params.add(phoneNumber);
        mysqlRequestDTO.setParams(params);
        mysqlRequestDTO.setPhoneNumber(phoneNumber);
        mysqlRequestDTO.setProjectTypeEnum(LittleProjectTypeEnum.ROCKETMQ);

        LOGGER.info("start query first login status param:{}", JSON.toJSONString(mysqlRequestDTO));
        CommonResponse<Integer> response = mysqlApi.update(mysqlRequestDTO);
        LOGGER.info("end query first login status param:{}, response:{}", JSON.toJSONString(mysqlRequestDTO), JSON.toJSONString(response));
    }

    /**
     * 这里写了这么多代码，其实就是一件事请，依据用户的ID获取用户的是否第一次登录标记，来判断用户使用第一次登录
     *
     * 主要是使用了dubbo接口，写了很多的样板代码。
     * 要是一般项目代码中会直接调用DAO的方法，这样看着是不是熟悉多了。
     * @param loginRequestDTO
     * @return
     */
    private boolean isFirstLogin(LoginRequestDTO loginRequestDTO) {
        MysqlRequestDTO mysqlRequestDTO = new MysqlRequestDTO();
        mysqlRequestDTO.setSql("select first_login_status from t_member where id = ? ");
        ArrayList<Object> params = new ArrayList<>();
        params.add(loginRequestDTO.getUserId());
        mysqlRequestDTO.setParams(params);
        mysqlRequestDTO.setPhoneNumber(loginRequestDTO.getPhoneNumber());
        mysqlRequestDTO.setProjectTypeEnum(LittleProjectTypeEnum.ROCKETMQ);

        LOGGER.info("start query first login status param:{}", JSON.toJSONString(mysqlRequestDTO));
        CommonResponse<List<Map<String, Object>>> response = mysqlApi.query(mysqlRequestDTO);
        LOGGER.info("end query first login status param:{}, response:{}", JSON.toJSONString(mysqlRequestDTO), JSON.toJSONString(response));
        if (Objects.equals(response.getCode(), ErrorCodeEnum.SUCCESS.getCode())
                && !CollectionUtils.isEmpty(response.getData())) {
            Map<String, Object> map = response.getData().get(0);
            return Objects.equals(Integer.valueOf(String.valueOf(map.get("first_login_status"))),
                    FirstLoginStatusEnum.YES.getStatus());
        }
        return false;
    }

    @Override
    public void resetFirstLoginStatus(String phoneNumber) {
        this.updateFirstLoginStatus(phoneNumber, FirstLoginStatusEnum.YES);
    }
}
